#include "config_api.h"
#include "config_factory.h"
#include "factory.h"
#include "factory_api.h"
#include "netdev_manager.h"
#include "webclient.h"
#include <rtdevice.h>
#include <rtthread.h>

#define LOG_TAG "net_test"
// #define DBG_LVL DBG_ERROR
#include "uc_log.h"
#include <rtdbg.h>

#define SET_POLICY_FAILED "set policy failed"
#define HTTP_DOWNLOAD_TEST_FAILED "http download test failed"
#define NET_TEST_PASSED "test passed"
#define NET_TEST_FAILED "test failed"
#define DOWNLOAD_TEST_TIMEOUT 10000 /* 10s */

#define GET_LOCAL_URL "http://www.rt-thread.com/service/rt-thread.txt"
#define CHARACTER_LENGTH 60

/* handle function, you can store data and so on */
static int http_download_callback(char *buffer, int length)
{
    int outindex, inindex = 0;
    int boundary;

    /* print the receive data */
    for (outindex = 0; outindex < length; outindex = outindex + inindex)
    {
        char print_buffer[CHARACTER_LENGTH + 1] = {0};
        char *point = RT_NULL;
        point = print_buffer;

        if (length - outindex > CHARACTER_LENGTH)
        {
            boundary = CHARACTER_LENGTH;
        }
        else
        {
            boundary = length - outindex;
        }

        for (inindex = 0; inindex < boundary; inindex++)
        {
            *point++ = buffer[outindex + inindex];
        }
        *point = 0;
        TRACE_I("%04d - %04d: %s", outindex, outindex + boundary - 1, print_buffer);
    }

    /* release this buffer if we have handled data */
    web_free(buffer);

    return RT_EOK;
}

int http_download_test(void)
{
    struct webclient_session *session = RT_NULL;
    rt_err_t result = RT_EOK;
    char *url = RT_NULL;
    int length = 0;
    int usage_flag = 0;
    int size = 200;

    url = web_strdup(GET_LOCAL_URL);

    TRACE_D("web shard download, url %s", url);

    /* sometime, the header bufsz can set more smaller */
    session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ / 4);
    if (session == RT_NULL)
    {
        result = -RT_ENOMEM;
        goto __exit;
    }

    /* get the real data length */
    webclient_shard_head_function(session, url, &length);
    TRACE_D("web shard download, length %s", length);

    /* register the handle function, you can handle data in the function */
    webclient_register_shard_position_function(session, http_download_callback);

    /* the "memory size" that you can provide in the project and url */
    result = webclient_shard_position_function(session, url, 0, length, size);
    if (result != WEBCLIENT_OK)
    {
        TRACE_E("web shard download, test failed!");
    }

    /* clear the handle function */
    webclient_register_shard_position_function(session, RT_NULL);

__exit:
    if (url)
    {
        web_free(url);
    }

    if (session)
    {
        webclient_close(session);
    }

    return result;
}

static int network_interface_test(void)
{
    char remarks[REMARK_LEN] = {0};

    if (0 != netdev_set_policy(NETDEV_INTERFACE))
    {
        rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_INTERFACE, SET_POLICY_FAILED);
        factory_test_result(NET_TEST, NETDEV_INTERFACE, FACTORY_TEST_FAIL, remarks);
        return -RT_ERROR;
    }

    if (RT_EOK != http_download_test())
    {
        rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_INTERFACE, HTTP_DOWNLOAD_TEST_FAILED);
        factory_test_result(NET_TEST, NETDEV_INTERFACE, FACTORY_TEST_FAIL, remarks);
        return -RT_ERROR;
    }

    rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_INTERFACE, NET_TEST_PASSED);
    factory_test_result(NET_TEST, NETDEV_INTERFACE, FACTORY_TEST_SUCCESS, remarks);

    return RT_EOK;
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
MSH_CMD_EXPORT_ALIAS(network_interface_test, net_test, net interface download test);
#endif /* FINSH_USING_MSH */

static int wifi_test(void)
{
    char remarks[REMARK_LEN] = {0};

    if (0 != netdev_set_policy(NETDEV_WIFI))
    {
        rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_WIFI, SET_POLICY_FAILED);
        factory_test_result(WIFI_TEST, NETDEV_WIFI, FACTORY_TEST_FAIL, remarks);
        return -RT_ERROR;
    }

    if (RT_EOK != http_download_test())
    {
        rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_WIFI, HTTP_DOWNLOAD_TEST_FAILED);
        factory_test_result(WIFI_TEST, NETDEV_WIFI, FACTORY_TEST_FAIL, remarks);
        return -RT_ERROR;
    }

    rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_WIFI, NET_TEST_PASSED);
    factory_test_result(WIFI_TEST, NETDEV_WIFI, FACTORY_TEST_SUCCESS, remarks);

    return RT_EOK;
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
MSH_CMD_EXPORT_ALIAS(wifi_test, wifi_test, wifi download test);
#endif /* FINSH_USING_MSH */

static int cat1_test(void)
{
    char remarks[REMARK_LEN] = {0};

    if (0 != netdev_set_policy(NETDEV_CAT1))
    {
        rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_CAT1, SET_POLICY_FAILED);
        factory_test_result(CAT1_TEST, NETDEV_CAT1, FACTORY_TEST_FAIL, remarks);
        return -RT_ERROR;
    }

    if (RT_EOK != http_download_test())
    {
        rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_CAT1, HTTP_DOWNLOAD_TEST_FAILED);
        factory_test_result(CAT1_TEST, NETDEV_CAT1, FACTORY_TEST_FAIL, remarks);
        return -RT_ERROR;
    }

    rt_snprintf(remarks, sizeof(remarks), "%s %s", NETDEV_CAT1, NET_TEST_PASSED);
    factory_test_result(CAT1_TEST, NETDEV_CAT1, FACTORY_TEST_SUCCESS, remarks);

    return RT_EOK;
}
#ifdef FINSH_USING_MSH
#include <finsh.h>
MSH_CMD_EXPORT_ALIAS(cat1_test, cat1_test, cat1 download test);
#endif /* FINSH_USING_MSH */

void network_test_init(void)
{
#ifdef RT_USING_WIFI
    wifi_on_func(NETDEV_WIFI);
    // 等待wifi连接
    rt_thread_delay(5000);
#endif
#ifdef PKG_USING_PPP_DEVICE
    cat1_on_func(NETDEV_CAT1);
#endif
}

int network_test(void)
{
    int result = RT_EOK, result1 = RT_EOK, result2 = RT_EOK;
    int ret = RT_EOK;
    unsigned int current_time = 0;

    // 网口测试
    current_time = facotry_start_output(NET_TEST);

    result = network_interface_test();
    facotry_result_output(NET_TEST, result, current_time);
    // wifi测试
    current_time = facotry_start_output(WIFI_TEST);

    result1 = wifi_test();
    facotry_result_output(WIFI_TEST, result1, current_time);

    // cat1 测试
    current_time = facotry_start_output(CAT1_TEST);

    result2 = cat1_test();
    facotry_result_output(CAT1_TEST, result2, current_time);

    if ((result | result1 | result2) == 0)
    {
        ret = RT_EOK;
    }
    else
    {
        ret = -RT_ERROR;
    }

    return ret;
}
